package com.tsmti.core.common.controller;

import com.alibaba.fastjson.JSON;
import com.tsmti.core.common.convert.DateConvertEditor;
import com.tsmti.core.common.convert.StringConvertEditor;
import com.tsmti.core.util.ConvertUtil;
import com.tsmti.core.util.ReportGenerateUtil;
import com.tsmti.core.util.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * @Package：com.tsmti.core.common.controller
 * @Class：BaseController
 * @Description： TODO
 * @Author：zcw
 * @Date：Created in 2018/4/20 14:39
 * @Company:
 * @Version：
 * @Modified By:
 */
public class BaseController {
    /**
     * 日志对象
     */
    protected Logger logger = LoggerFactory.getLogger(getClass());

    private final static String SEPARATOR = "/";
    private String viewPrefix;

    protected BaseController() {
        setViewPrefix(getDefaultViewPrefix());
    }

    /**
     * 返回JSON字符串
     *
     * @param response
     * @param object
     * @return
     */
    protected void printString(HttpServletResponse response, Object object) {
        printString(response, JSON.toJSONString(object));
    }

    /**
     * 打印字符串到页面
     *
     * @param response
     * @param string
     * @return
     */
    protected void printString(HttpServletResponse response, String string) {
        try {
            response.reset();
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            response.getWriter().print(string);
        } catch (IOException e) {

        }
    }

    /**
     * 初始化数据绑定
     *
     * @param binder
     */
    @InitBinder
    void initBinder(ServletRequestDataBinder binder) {
        // 将所有传递进来的String进行HTML编码，防止XSS攻击
        // 这个会导致数据库数据
        binder.registerCustomEditor(String.class, new StringConvertEditor());
        // 日期格式
        binder.registerCustomEditor(Date.class, new DateConvertEditor());
    }

    /**
     * 当前模块 视图的前缀 默认 1、获取当前类头上的@RequestMapping中的value作为前缀 2、如果没有就使用当前模型小写的简单类名
     */
    public void setViewPrefix(String viewPrefix) {
        if (viewPrefix.startsWith(SEPARATOR)) {
            viewPrefix = viewPrefix.substring(1);
        }
        this.viewPrefix = viewPrefix;
    }

    public String getViewPrefix() {
        return viewPrefix;
    }

    /**
     * 获取视图名称：即prefixViewName + "/" + suffixName
     *
     * @return
     */
    public String display(String suffixName) {
        if (!suffixName.startsWith(SEPARATOR)) {
            suffixName = SEPARATOR + suffixName;
        }
        String prefixName = getDefaultViewPrefix();
        return prefixName + suffixName;
    }

    protected String getDefaultViewPrefix() {
        String currentViewPrefix = "";
        RequestMapping requestMapping = AnnotationUtils.findAnnotation(getClass(), RequestMapping.class);
        if (requestMapping != null && requestMapping.value().length > 0) {
            currentViewPrefix = requestMapping.value()[0];
        }
        if (StringUtils.isEmpty(currentViewPrefix)) {
            currentViewPrefix = this.getClass().getSimpleName().replace("Controller", "").toLowerCase();
        }

        return currentViewPrefix;
    }
    /**
     * 遍历类中的所有属性及赋值到报告模板中
     *
     * @param o      实体类
     * @param tag    模板内容
     * @param prefix 前缀
     * @return
     */
    public String reflect(Object o, String tag, String prefix) {
     /*   if (StringUtils.isNotEmpty(prefix)) {
            prefix += ".";
        }*/
        //获取参数类
        Class cls = o.getClass();
        //将参数类转换为对应属性数量的Field类型数组（即该类有多少个属性字段 N 转换后的数组长度即为 N）
        Field[] fields = cls.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            Field f = fields[i];
            f.setAccessible(true);
            try {
                Object oo = f.get(o);
                String propertyTypeName = String.valueOf(f.getGenericType()).replace("class", "").trim();
                String value = "";
                if (oo != null) {
                    if (propertyTypeName.equals(int.class.getName())
                            || propertyTypeName.equals(Integer.class.getName())) {
                        value = String.valueOf(oo);
                    } else if (propertyTypeName.equals(long.class.getName())
                            || propertyTypeName.equals(Long.class.getName())) {
                        value = String.valueOf(oo);
                    } else if (propertyTypeName.equals(double.class.getName())
                            || propertyTypeName.equals(Double.class.getName())) {
                        value = String.valueOf(oo);
                    } else if (propertyTypeName.equals(float.class.getName())
                            || propertyTypeName.equals(Float.class.getName())) {
                        value = String.valueOf(oo);
                    } else if (propertyTypeName.equals(byte.class.getName())
                            || propertyTypeName.equals(Byte.class.getName())) {
                        value = String.valueOf(oo);
                    } else if (propertyTypeName.equals(short.class.getName())
                            || propertyTypeName.equals(Short.class.getName())) {
                        value = String.valueOf(oo);
                    } else if (propertyTypeName.equals(char[].class.getName())
                            || propertyTypeName.equals(Character[].class.getName())) {
                        value = String.valueOf(oo);
                    } else if (propertyTypeName.equals(boolean.class.getName())
                            || propertyTypeName.equals(Boolean.class.getName())) {
                        value = String.valueOf(oo);
                    } else if (propertyTypeName.equals(String.class.getName())) {
                        value = String.valueOf(oo);
                    } else if (propertyTypeName.equals(java.util.Date.class.getName())) {
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        value = sdf.format(oo);
                    } else if (propertyTypeName.indexOf(List.class.getName()) > -1) {
                        Document doc = Jsoup.parse(tag);
                        Elements table = doc.select("table[name=" + f.getName() + "]");
                        List<Object> list = (List<Object>) oo;
                        for (Object obj : list) {
                            Field[] detailFields = obj.getClass().getDeclaredFields();
                            String tr = table.select("tr").get(1).outerHtml();
                            for (int j = 0; j < detailFields.length; j++) {
                                Field detailField = detailFields[j];
                                detailField.setAccessible(true);
                                Object detailOo = detailField.get(obj);
                                if (detailOo != null) {
                                    tr = tr.replaceAll(prefix + detailField.getName(), String.valueOf(detailOo));
                                }
                            }
                            value += tr;
                        }
                        table.select("tr").get(1).remove();
                        table.append(value);
                        tag = doc.outerHtml();
                        continue;
                    }

                }
                tag = tag.replaceAll(prefix + "." + f.getName()+"#", value);
                //f.getName()得到对应字段的属性名，f.get(o)得到对应字段属性值,f.getGenericType()得到对应字段的类型
                System.out.println("属性名：" + f.getName() + "；属性值：" + f.get(o) + ":" + String.valueOf(f.get(o)) + ";字段类型：" + f.getGenericType());
            } catch (IllegalArgumentException | IllegalAccessException e) {
                // TODO Auto-generated catch block
                logger.error("异常错误",e);
                e.printStackTrace();
            }
        }
        return tag;
    }

    /**
     * 模版赋值
     *
     * @param o
     * @param tag
     * @return
     */
    public String reflect2(Object o, String tag) {
        Document doc = Jsoup.parse(tag);
        Elements input = doc.getElementsByTag("input");
        Elements table = doc.getElementsByTag("table");
        Elements img = doc.getElementsByTag("img");
        try {
            Class cls = o.getClass();
            Field[] fields = cls.getDeclaredFields();
            for (Element element : input) {
                String name = element.attr("name");
                if ("text".equals(element.attr("type"))) {
                    Field field = o.getClass().getDeclaredField(name);
                    field.setAccessible(true);
                    Object value = field.get(o);
                    element.tagName("span");
                    element.text(ConvertUtil.null2String(value));
                }
                if ("checkbox".equals(element.attr("type"))) {
                    Field field = o.getClass().getDeclaredField(name);
                    field.setAccessible(true);
                    String value = ConvertUtil.null2String(field.get(o));
                    if (value.equals(element.attr("value"))) {
                        element.attr("checked", true);
                    }
                }
            }
            for (Element element : table) {
                String name = element.attr("name");
                if (StringUtils.isNotEmpty(name)) {
                    Field field = o.getClass().getDeclaredField(name);
                    field.setAccessible(true);
                    List<Object> list = (List<Object>) field.get(o);
                    for (Object obj : list) {
                        Field[] detailFields = obj.getClass().getDeclaredFields();
                        String tr = element.select("tr").get(1).outerHtml();
                        for (int j = 0; j < detailFields.length; j++) {
                            Field detailField = detailFields[j];
                            detailField.setAccessible(true);
                            Object detailOo = detailField.get(obj);
                            if (detailOo != null) {
                                tr = tr.replaceAll(detailField.getName(), ConvertUtil.null2String(detailOo));
                            }
                        }
                        element.append(tr);
                    }
                    element.select("tr").get(1).remove();
                }
            }
            for(Element element : img) {
                String src = element.attr("src");
                String name = element.attr("name");
                if (StringUtils.isNotEmpty(name)) {
                    Field field = o.getClass().getDeclaredField(name);
                    field.setAccessible(true);
                    String value =ConvertUtil.null2String(field.get(o));
                    src = src.replaceAll("#"+field.getName(), value);
                }
                element.attr("src", src);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return doc.outerHtml();
    }

    @RequestMapping(value = "/GetImg*", method = RequestMethod.GET)
    public void getImg(HttpServletRequest request, HttpServletResponse response) {
        String barcode = ConvertUtil.null2String(request.getParameter("barcode"));
        OutputStream os = null;
        try {
            int count = 0;
            byte[] buffer = new byte[1024 * 8];
            buffer = ReportGenerateUtil.create128CodeImg(barcode);
            response.getOutputStream().write(buffer);
            response.getOutputStream().flush();
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            response.getOutputStream().close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
